/**
 * 变更比对服务
 * 用于比对编辑器和影子空间的快照，生成 ChangesView 支持的格式
 */

import {
  FileSnapshot,
  FileChangeWithSide,
  ChangeAction,
  CompareSide,
} from '@/types/modules/editor/types/commit.type';

/**
 * 快照比对选项
 */
export interface SnapshotCompareOptions {
  /** 源方标识（如 'editor'） */
  sourceLabel?: string;
  /** 目标方标识（如 'shadow-space'） */
  targetLabel?: string;
  /** 项目ID */
  projectId?: string;
  /** 影子空间ID */
  shadowSpace?: string;
}

/**
 * 变更比对结果
 */
export interface ChangeCompareResult {
  /** 变更列表（ChangesView 格式） */
  changes: FileChangeWithSide<any>[];
  /** 统计信息 */
  summary: {
    total: number;
    added: number;
    modified: number;
    deleted: number;
  };
  /** 需要推送的文件列表 */
  filesToPush: string[];
  /** 需要从空间拉取的文件列表 */
  filesToPull: string[];
}

/**
 * 变更比对服务
 */
export class ChangeCompareService {
  /**
   * 比对编辑器和影子空间快照
   * 现在 hash 算法已统一，可以直接比对 hash
   * 当 hash 不同时，通过时间戳判断谁是最新版本
   */
  async compareSnapshots(
    editorSnapshots: FileSnapshot[],
    spaceSnapshots: FileSnapshot[],
    options: SnapshotCompareOptions = {},
  ): Promise<ChangeCompareResult> {
    const {
      sourceLabel = 'editor',
      targetLabel = 'shadow-space',
      projectId,
      shadowSpace,
    } = options;

    console.log(
      `[ChangeCompareService] 开始比对快照: ${editorSnapshots.length} vs ${spaceSnapshots.length}`,
    );

    // 直接实现比对逻辑
    const changes: FileChangeWithSide<any>[] = [];
    const filesToPush: string[] = [];
    const filesToPull: string[] = [];

    // 构建映射表
    const editorMap = new Map(editorSnapshots.map((f) => [f.path, f]));
    const spaceMap = new Map(spaceSnapshots.map((f) => [f.path, f]));

    // 检测编辑器的变更（新增、修改）
    for (const [path, editorFile] of editorMap) {
      const spaceFile = spaceMap.get(path);

      if (!spaceFile) {
        // 编辑器新增的文件 → 推送到空间
        const change: FileChangeWithSide<any> = {
          id: `add_${path}`,
          action: 'add' as ChangeAction,
          path,
          side: 'source' as CompareSide,
          sourceLabel,
          targetLabel,
          editorHash: editorFile.hash,
          spaceHash: null,
        };
        changes.push(change);
        filesToPush.push(path);
      } else if (editorFile.hash !== spaceFile.hash) {
        // Hash 不同，需要判断谁是最新版本
        const editorModify = editorFile.modify || 0;
        const spaceModify = spaceFile.modify || 0;

        console.log(`[ChangeCompareService] 检测到文件差异: ${path}`, {
          editorHash: editorFile.hash?.substring(0, 16),
          spaceHash: spaceFile.hash?.substring(0, 16),
          editorModify: new Date(editorModify).toISOString(),
          spaceModify: new Date(spaceModify).toISOString(),
          editorUpdateBy: editorFile.updateBy,
          spaceUpdateBy: spaceFile.updateBy,
        });

        // 🔥 关键逻辑：根据时间戳判断方向
        if (editorModify > spaceModify) {
          // 编辑器更新 → 推送到空间
          console.log(`[ChangeCompareService] → 编辑器更新，需要推送: ${path}`);
          const change: FileChangeWithSide<any> = {
            id: `modify_${path}`,
            action: 'modify' as ChangeAction,
            path,
            side: 'source' as CompareSide,
            sourceLabel,
            targetLabel,
            editorHash: editorFile.hash,
            spaceHash: spaceFile.hash,
          };
          changes.push(change);
          filesToPush.push(path);
        } else if (spaceModify > editorModify) {
          // 空间更新 → 拉取到编辑器
          console.log(`[ChangeCompareService] ← 空间更新，需要拉取: ${path}`);
          const change: FileChangeWithSide<any> = {
            id: `modify_${path}`,
            action: 'modify' as ChangeAction,
            path,
            side: 'target' as CompareSide,
            sourceLabel: targetLabel,
            targetLabel: sourceLabel,
            editorHash: editorFile.hash,
            spaceHash: spaceFile.hash,
          };
          changes.push(change);
          filesToPull.push(path);
        } else {
          // 时间戳相同但 hash 不同 → 可能是冲突，默认以编辑器为准
          console.warn(`[ChangeCompareService] ⚠️ 时间戳相同但内容不同，默认以编辑器为准: ${path}`);
          const change: FileChangeWithSide<any> = {
            id: `modify_${path}`,
            action: 'modify' as ChangeAction,
            path,
            side: 'source' as CompareSide,
            sourceLabel,
            targetLabel,
            editorHash: editorFile.hash,
            spaceHash: spaceFile.hash,
            conflict: true, // 标记为潜在冲突
          };
          changes.push(change);
          filesToPush.push(path);
        }
      }
    }

    // 检测空间独有的文件（编辑器已删除或空间新增）
    for (const [path, spaceFile] of spaceMap) {
      const editorFile = editorMap.get(path);

      if (!editorFile) {
        // 空间独有的文件 → 拉取到编辑器（或编辑器已删除）
        const change: FileChangeWithSide<any> = {
          id: `delete_${path}`,
          action: 'delete' as ChangeAction,
          path,
          side: 'target' as CompareSide,
          sourceLabel: targetLabel,
          targetLabel: sourceLabel,
          editorHash: null,
          spaceHash: spaceFile.hash,
        };
        changes.push(change);
        filesToPull.push(path);
      }
    }

    // 计算统计信息
    const summary = {
      total: changes.length,
      added: changes.filter((c) => c.action === 'add').length,
      modified: changes.filter((c) => c.action === 'modify').length,
      deleted: changes.filter((c) => c.action === 'delete').length,
    };

    console.log(`[ChangeCompareService] 比对完成: ${changes.length} 个变更`);
    console.log(`[ChangeCompareService] 需要推送: ${filesToPush.length} 个文件`);
    console.log(`[ChangeCompareService] 需要拉取: ${filesToPull.length} 个文件`);

    return {
      changes,
      summary,
      filesToPush,
      filesToPull,
    };
  }

  /**
   * 生成变更摘要信息
   */
  generateChangeSummary(result: ChangeCompareResult): string {
    const { summary, filesToPush, filesToPull } = result;

    if (summary.total === 0) {
      return '没有检测到变更';
    }

    const parts: string[] = [];

    if (filesToPush.length > 0) {
      parts.push(`需要推送 ${filesToPush.length} 个文件`);
    }

    if (filesToPull.length > 0) {
      parts.push(`需要拉取 ${filesToPull.length} 个文件`);
    }

    return parts.join('，') || `检测到 ${summary.total} 个变更`;
  }

  /**
   * 过滤需要推送的变更
   */
  filterPushChanges(changes: FileChangeWithSide<any>[]): FileChangeWithSide<any>[] {
    return changes.filter((change) => change.side === 'source');
  }

  /**
   * 过滤需要拉取的变更
   */
  filterPullChanges(changes: FileChangeWithSide<any>[]): FileChangeWithSide<any>[] {
    return changes.filter((change) => change.side === 'target');
  }

  /**
   * 转换为 ChangesView 需要的格式
   */
  formatForChangesView(
    changes: FileChangeWithSide<any>[],
    title: string = '文件变更',
  ): {
    title: string;
    changes: FileChangeWithSide<any>[];
    stats: {
      total: number;
      added: number;
      modified: number;
      deleted: number;
    };
  } {
    const stats = {
      total: changes.length,
      added: changes.filter((c) => c.action === 'add').length,
      modified: changes.filter((c) => c.action === 'modify').length,
      deleted: changes.filter((c) => c.action === 'delete').length,
    };

    return {
      title,
      changes,
      stats,
    };
  }
}

/**
 * 创建变更比对服务实例
 */
export function createChangeCompareService(): ChangeCompareService {
  return new ChangeCompareService();
}

/**
 * 快速比对编辑器和影子空间快照
 */
export async function quickCompareSnapshots(
  editorSnapshots: FileSnapshot[],
  spaceSnapshots: FileSnapshot[],
  options: SnapshotCompareOptions = {},
): Promise<ChangeCompareResult> {
  const service = createChangeCompareService();
  return service.compareSnapshots(editorSnapshots, spaceSnapshots, options);
}

/**
 * 模拟从CLI响应中解析影子空间快照
 * 实际使用时需要根据CLI的响应格式调整
 */
export function parseSpaceSnapshotsFromResponse(response: any): FileSnapshot[] {
  // 这里需要根据实际的CLI响应格式来解析
  // 示例格式：
  if (response?.data?.spaceSnapshots) {
    return response.data.spaceSnapshots.map((item: any) => ({
      path: item.path,
      modify: item.modify || Date.now(),
      hash: item.remoteHash || item.hash, // 优先使用云端哈希
      updateBy: item.updateBy || 'shadow-space',
    }));
  }

  return [];
}

/**
 * 使用示例和测试函数
 */
export async function exampleUsage() {
  console.log('=== 变更比对服务示例 ===');

  // 模拟编辑器快照
  const editorSnapshots: FileSnapshot[] = [
    { path: 'pages/home.tsx', modify: Date.now(), hash: 'editor-hash-1', updateBy: 'editor' },
    { path: 'pages/about.tsx', modify: Date.now(), hash: 'editor-hash-2', updateBy: 'editor' },
    {
      path: 'components/Button.tsx',
      modify: Date.now(),
      hash: 'editor-hash-3',
      updateBy: 'editor',
    },
  ];

  // 模拟影子空间快照
  const spaceSnapshots: FileSnapshot[] = [
    {
      path: 'pages/home.tsx',
      modify: Date.now() - 60000,
      hash: 'space-hash-1',
      updateBy: 'shadow-space',
    },
    {
      path: 'pages/about.tsx',
      modify: Date.now(),
      hash: 'editor-hash-2',
      updateBy: 'shadow-space',
    }, // 相同
    {
      path: 'components/Modal.tsx',
      modify: Date.now(),
      hash: 'space-hash-4',
      updateBy: 'shadow-space',
    }, // 空间新增
  ];

  // 比对快照
  const result = await quickCompareSnapshots(editorSnapshots, spaceSnapshots, {
    sourceLabel: 'editor',
    targetLabel: 'shadow-space',
    projectId: 'test-project',
    shadowSpace: 'main',
  });

  console.log('比对结果:', result.summary);
  console.log('需要推送的文件:', result.filesToPush);
  console.log('需要拉取的文件:', result.filesToPull);

  // 生成 ChangesView 格式
  const service = createChangeCompareService();
  const pushChanges = service.formatForChangesView(
    service.filterPushChanges(result.changes),
    '需要推送到影子空间',
  );
  const pullChanges = service.formatForChangesView(
    service.filterPullChanges(result.changes),
    '需要从影子空间拉取',
  );

  console.log('推送变更格式:', pushChanges);
  console.log('拉取变更格式:', pullChanges);

  return { result, pushChanges, pullChanges };
}

// 导出给浏览器控制台使用
if (typeof window !== 'undefined') {
  (window as any).changeCompareService = {
    createChangeCompareService,
    quickCompareSnapshots,
    parseSpaceSnapshotsFromResponse,
    exampleUsage,
  };

  console.log('💡 变更比对服务已加载！');
  console.log('使用 changeCompareService.exampleUsage() 查看示例');
}
